package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.account.client.UserAccountFeignClient;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.strategy.ItemTypeStrategy;
import com.atguigu.tingshu.user.strategy.StrategyFactory;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;

	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;


	@Autowired
	private WxMaService wxMaService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private RabbitService rabbitService;
    @Qualifier("com.atguigu.tingshu.user.client.UserInfoFeignClient")
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

	////根据用户id查询用户是否购买专辑或者声音
	@Override
	public Map<Long, Integer> userIsPaidTrack(Long userId,
											  Long albumId,
											  List<Long> trackIdList) {
		//1 根据用户id + 专辑id查询用户是否购买专辑  user_paid_album
		LambdaQueryWrapper<UserPaidAlbum> wrapper01 = new LambdaQueryWrapper<>();
		wrapper01.eq(UserPaidAlbum::getUserId, userId);
		wrapper01.eq(UserPaidAlbum::getAlbumId, albumId);
		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(wrapper01);

		//2 如果用户购买过专辑，把专辑里面所有声音购买过 map的key声音id value是1
		if(userPaidAlbum != null) {
			Map<Long, Integer> map = new HashMap<>();
			trackIdList.forEach(trackId->{
				map.put(trackId,1);
			});
			return map;
		} else {
			//3 如果用户没有买过专辑，根据用户id + 声音id查询购买哪些声音  user_paid_track
			LambdaQueryWrapper<UserPaidTrack> wrapper02 = new LambdaQueryWrapper<>();
			wrapper02.eq(UserPaidTrack::getUserId, userId);
			// in (1,2,3)
			wrapper02.in(UserPaidTrack::getTrackId, trackIdList);
			List<UserPaidTrack> userPaidTrackList =
					userPaidTrackMapper.selectList(wrapper02);

			//	获取到用户购买声音Id 集合
			List<Long> userPaidTrackIdList = userPaidTrackList.stream()
					.map(UserPaidTrack::getTrackId)
					.collect(Collectors.toList());

			Map<Long, Integer> map = new HashMap<>();

			// 所有：[1,2,3,4,5]      trackIdList
			// 购买：[1,2,3]          userPaidTrackIdList
			//4 根据查询购买声音，和所有声音比较，如果购买过 map的key声音id value是1
			//                                 如果没有购买过 map的key声音id value是0
			trackIdList.forEach(trackId->{
				boolean contains = userPaidTrackIdList.contains(trackId);
				if(contains) { //包含，购买过
					//	用户已购买声音
					map.put(trackId,1);
				} else { //不包含
					map.put(trackId,0);
				}
			});
			return map;
		}
	}

	////用户是否购买专辑
	@Override
	public Boolean isPaidAlbum(Long albumId, Long userId) {
		LambdaQueryWrapper<UserPaidAlbum> wrapper01 = new LambdaQueryWrapper<>();
		wrapper01.eq(UserPaidAlbum::getAlbumId, albumId);
		wrapper01.eq(UserPaidAlbum::getUserId, userId);
		Long count = userPaidAlbumMapper.selectCount(wrapper01);
		return count>0;  //1>0 true  0>0 false

//		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(wrapper01);
//		if(userPaidAlbum != null) {
//			return true;
//		} else {
//			return false;
//		}
	}

	//根据专辑id + 用户id获取购买声音id列表
	@Override
	public List<Long> findPaidUserTrackList(Long userId, Long albumId) {
		LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(UserPaidTrack::getUserId, userId);
		wrapper.eq(UserPaidTrack::getAlbumId, albumId);
		List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(wrapper);
		// 获取到已购买的声音集合Id 列表
		List<Long> trackIdList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
		// 返回集合数据
		return trackIdList;
	}

	//添加购买记录
	@Autowired
	private TrackInfoFeignClient trackInfoFeignClient;

	@Autowired
	private VipServiceConfigMapper vipServiceConfigMapper;

	@Autowired
	private UserVipServiceMapper userVipServiceMapper;

	//使用策略模式优化：添加购买记录
	@Autowired
	private StrategyFactory strategyFactory;
	@Override
	public void savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
		//// 1001-专辑 1002-声音 1003-vip会员
		String itemType = userPaidRecordVo.getItemType();

		//1 根据购买类型，获取不同的实现类
		ItemTypeStrategy strategy = strategyFactory.getStrategy(itemType);

		//2 调用不同实现类里面添加购买记录方法
		strategy.savePaidRecord(userPaidRecordVo);
	}

	//更新过期vip用户状态
	@Override
	public void updateVipExpireStatus() {
		userInfoMapper.updateVipExpireStatus();
	}

	@Autowired
	private UserAccountFeignClient userAccountFeignClient;

	//之前没有使用策略模式添加购买记录方法
	public void savePaidRecord1(UserPaidRecordVo userPaidRecordVo) {
		//获取购买类型  1001-专辑 1002-声音 1003-vip会员
		String itemType = userPaidRecordVo.getItemType();
		if("1001".equals(itemType)) { //购买专辑
			//TODO 判断，购买记录不能重复添加

			UserPaidAlbum userPaidAlbum = new UserPaidAlbum();
			//用户id
			userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
			//订单变化
			userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
			//  专辑Id
			Long albumId = userPaidRecordVo.getItemIdList().get(0);
			userPaidAlbum.setAlbumId(albumId);
			//调用方法
			userPaidAlbumMapper.insert(userPaidAlbum);

		} else if("1002".equals(itemType)) { //购买声音
			//TODO 判断，购买记录不能重复添加

			//远程调用：根据声音id获取声音对象，从声音对象里面获取专辑id
			Long id = userPaidRecordVo.getItemIdList().get(0);
			Result<TrackInfo> result = trackInfoFeignClient.getTrackInfo(id);
			TrackInfo trackInfo = result.getData();

			List<Long> itemIdList = userPaidRecordVo.getItemIdList();
			itemIdList.forEach(trackId->{
				UserPaidTrack userPaidTrack = new UserPaidTrack();
				userPaidTrack.setTrackId(trackId);
				userPaidTrack.setUserId(userPaidRecordVo.getUserId());
				userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
				//设置专辑id
				Long albumId = trackInfo.getAlbumId();
				userPaidTrack.setAlbumId(albumId);
				userPaidTrackMapper.insert(userPaidTrack);
			});
		} else { //购买vip
			Long userId = userPaidRecordVo.getUserId();
			//根据userId获取用户信息
			UserInfo userInfo = userInfoMapper.selectById(userId);

			//计算vip过期时间
			Date currentDate = new Date();

			////如果用户是没有过期vip，过期时间=原有过期时间+开通月份
			if(userInfo.getIsVip().intValue()==1
					&& userInfo.getVipExpireTime().after(new Date())) {
				currentDate = userInfo.getVipExpireTime();
			}

			//如果用户不是vip，     过期时间=当前时间+开通月份
			Long vipId = userPaidRecordVo.getItemIdList().get(0);
			//根据vipid查询开通月份
			VipServiceConfig vipServiceConfig =
					vipServiceConfigMapper.selectById(vipId);
			Integer serviceMonth = vipServiceConfig.getServiceMonth();
			//过期时间= 当前时间+开通月份
			Date expireDate =
					new LocalDateTime(currentDate)
							 .plusMonths(serviceMonth).toDate();

			//user_vip_service
			UserVipService userVipService = new UserVipService();
			userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
			userVipService.setUserId(userPaidRecordVo.getUserId());
			userVipService.setStartTime(new Date());
			userVipService.setExpireTime(expireDate);
			//  保存
			userVipServiceMapper.insert(userVipService);

			//  修改user_info.is_vip=1;
			userInfo.setIsVip(1);
			//  设置过期时间
			userInfo.setVipExpireTime(expireDate);
			//  修改
			this.userInfoMapper.updateById(userInfo);
		}
	}

	///
	@GlobalTransactional
	@Override
	public void saveUser(UserInfo userInfo) {
		//添加用户信息
		this.save(userInfo);
		//int i = 1/0;

		//初始化账户
		//方法一：远程调用 在service-account创建初始化接口
		// 在service-user进行远程调用实现
		userAccountFeignClient.initUser(userInfo.getId());
	}
}
